Introdução¶
Mineração de dados sobre os acidentes de trânsito nas rodovias federais brasileiras durante o perÃodo de tempo de Janeiro de 2023 até Janeiro de 2025. Foi utilizado no treinamento dos modelos os algoritimos Naive Bayes, Random Forest, SVM e RBFNN. A análise do impacto das váriaveis no modelo Random Forest foi feita com base no SHAP values que utiliza a teoria dos jogos para identificar a contribuição dos envolvidos no treinamento no resultado final. Os datasets foram disponibilizados pelo Plano de Dados Abertos da PRF através do site: https://www.gov.br/prf/pt-br/acesso-a-informacao/dados-abertos/dados-abertos-da-prf na categoria de Agrupados por ocorrência.
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.naive_bayes import GaussianNB
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import accuracy_score, classification_report
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
import shap
Carregamento e transformação dos dados¶
df1 = pd.read_csv("datatran2025.csv", encoding="ANSI", delimiter=";")
df2 = pd.read_csv("datatran2024.csv", encoding="ANSI", delimiter=";")
df3 = pd.read_csv("datatran2023.csv", encoding="ANSI", delimiter=";")
df = pd.concat([df1, df2, df3])
df
| id | data_inversa | dia_semana | horario | uf | br | km | municipio | causa_acidente | tipo_acidente | ... | feridos_graves | ilesos | ignorados | feridos | veiculos | latitude | longitude | regional | delegacia | uop | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 652493.0 | 2025-01-01 | quarta-feira | 06:20:00 | SP | 116 | 225 | GUARULHOS | Reação tardia ou ineficiente do condutor | Tombamento | ... | 0 | 0 | 1 | 1 | 2 | -23.485868 | -46.540753 | SPRF-SP | DEL01-SP | UOP01-DEL01-SP |
| 1 | 652519.0 | 2025-01-01 | quarta-feira | 07:50:00 | CE | 116 | 546,2 | PENAFORTE | Pista esburacada | Colisão frontal | ... | 0 | 1 | 4 | 1 | 6 | -7.812288 | -39.083333 | SPRF-CE | DEL05-CE | UOP03-DEL05-CE |
| 2 | 652522.0 | 2025-01-01 | quarta-feira | 08:45:00 | PR | 369 | 88,2 | CORNELIO PROCOPIO | Reação tardia ou ineficiente do condutor | Colisão traseira | ... | 0 | 2 | 0 | 3 | 2 | -23.182565 | -50.637228 | SPRF-PR | DEL07-PR | UOP05-DEL07-PR |
| 3 | 652544.0 | 2025-01-01 | quarta-feira | 11:00:00 | PR | 116 | 74 | CAMPINA GRANDE DO SUL | Reação tardia ou ineficiente do condutor | SaÃda de leito carroçável | ... | 0 | 4 | 0 | 1 | 2 | -25.365177 | -49.04223 | SPRF-PR | DEL01-PR | UOP02-DEL01-PR |
| 4 | 652549.0 | 2025-01-01 | quarta-feira | 09:30:00 | MG | 251 | 471 | FRANCISCO SA | Velocidade IncompatÃvel | Colisão frontal | ... | 1 | 1 | 2 | 2 | 4 | -16.468013 | -43.431213 | SPRF-MG | DEL12-MG | UOP01-DEL12-MG |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 67761 | 619297.0 | 2023-04-19 | quarta-feira | 20:50:00 | PR | 376 | 475 | PONTA GROSSA | Pedestre andava na pista | Atropelamento de Pedestre | ... | 0 | 4 | 0 | 0 | 2 | -25,05467785 | -50,22938892 | NaN | NaN | NaN |
| 67762 | 619475.0 | 2023-06-20 | terça-feira | 20:30:00 | MA | 222 | 206,5 | ITAPECURU MIRIM | Acessar a via sem observar a presença dos outr... | Colisão transversal | ... | 0 | 1 | 0 | 1 | 2 | -3,40552588 | -44,35174989 | NaN | NaN | NaN |
| 67763 | 619476.0 | 2023-05-18 | quinta-feira | 06:15:00 | ES | 101 | 62,7 | SAO MATEUS | Conversão proibida | Colisão transversal | ... | 1 | 0 | 0 | 3 | 2 | -18,69020499 | -39,86154403 | NaN | NaN | NaN |
| 67764 | 619913.0 | 2023-08-22 | terça-feira | 15:00:00 | MG | 50 | 15 | UBERLANDIA | Acumulo de areia ou detritos sobre o pavimento | Tombamento | ... | 1 | 0 | 0 | 1 | 1 | -18,91385522 | -48,17243636 | NaN | NaN | NaN |
| 67765 | 620943.0 | 2023-08-14 | segunda-feira | 13:30:00 | RJ | 116 | 148 | DUQUE DE CAXIAS | Chuva | Queda de ocupante de veÃculo | ... | 0 | 0 | 0 | 1 | 1 | -22,6723488 | -43,28215398 | NaN | NaN | NaN |
146400 rows × 30 columns
# Remover colunas irrelevantes
colunas_remover = ['id', 'horario', 'uf', 'km', 'municipio', 'pessoas', 'ignorados', 'regional', 'delegacia', 'uop', 'mortos', 'feridos_leves', 'feridos_graves', 'ilesos', 'br']
df.drop(columns=colunas_remover, inplace=True)
df.shape
(146400, 15)
#Para facilitar a leitura do notebook coloquei até 20 categorias, caso queira ver todas as categorias basta tirar a condicional
for coluna, dados in df.items():
print(coluna)
categorias = dados.unique()
i = 0
for categoria in categorias:
if (i > 20):
print("...")
break
else:
print(f"{categoria} ")
i += 1
print()
data_inversa 2025-01-01 00:00:00 2025-01-02 00:00:00 2025-01-03 00:00:00 2025-01-04 00:00:00 2025-01-05 00:00:00 2025-01-06 00:00:00 2025-01-07 00:00:00 2025-01-08 00:00:00 2025-01-09 00:00:00 2025-01-10 00:00:00 2025-01-11 00:00:00 2025-01-12 00:00:00 2025-01-13 00:00:00 2025-01-14 00:00:00 2025-01-15 00:00:00 2025-01-16 00:00:00 2025-01-17 00:00:00 2025-01-18 00:00:00 2025-01-19 00:00:00 2025-01-20 00:00:00 2025-01-21 00:00:00 ... dia_semana Quarta-feira Quinta-feira Sexta-feira Sábado Domingo Segunda-feira Terça-feira causa_acidente Reação tardia ou ineficiente do condutor Outros Velocidade IncompatÃvel Transitar na contramão Ausência de reação do condutor Demais falhas mecânicas ou elétricas Ingestão de álcool pelo condutor Condutor Dormindo Manobra de mudança de faixa Acessar a via sem observar a presença dos outros veÃculos Condutor deixou de manter distância do veÃculo da frente Ultrapassagem Indevida Desrespeitar a preferência no cruzamento Animais na Pista Trafegar com motocicleta (ou similar) entre as faixas Avarias e/ou desgaste excessivo no pneu tipo_acidente Tombamento Colisão frontal Colisão traseira SaÃda de leito carroçável Incêndio Colisão com objeto Colisão lateral mesmo sentido Colisão lateral sentido oposto Queda de ocupante de veÃculo Engavetamento Derramamento de carga Colisão transversal Atropelamento de Pedestre Capotamento Atropelamento de Animal Eventos atÃpicos Sinistro pessoal de trânsito classificacao_acidente Com VÃtimas Feridas Com VÃtimas Fatais Sem VÃtimas fase_dia Pleno dia Anoitecer Plena Noite Amanhecer sentido_via Decrescente Crescente Não Informado condicao_metereologica Céu Claro Sol Chuva Nublado Garoa/Chuvisco Vento Nevoeiro/Neblina Granizo Neve tipo_pista Múltipla Simples Dupla tracado_via Reta;Declive Reta Reta;Aclive Curva;Declive Curva Outros Declive;Reta Aclive;Reta Interseção de Vias uso_solo Sim Não feridos 1 3 2 0 4 7 15 6 5 9 11 49 19 8 10 20 14 22 27 12 13 ... veiculos 2 6 4 5 1 3 7 8 9 10 12 11 13 15 20 14 17 16 26 24 18 ... latitude -23.48586772 -7.812288 -23.182565 -25.36517687 -16.46801304 -16.04148578 -30.739714 -27.60001226 -21.16328873 -8.47503105 -28.42800492 -20.17327539 -6.846113 -27.370375 -25.59505309 -7.2075 -9.77791545 -25.5216371 -20.60236514 -11.9396379 -8.09414193 ... longitude -46.54075317 -39.08333306 -50.637228 -49.04223028 -43.43121303 -57.25884017 -51.62594 -48.6226467 -42.37968988 -41.0137105 -48.88171497 -44.37545454 -38.366341 -51.993419 -49.31630659 -35.5248 -54.90365982 -53.5943858 -43.80699874 -55.51573103 -35.03716601 ... mes 1 2 3 4 5 6 7 8 9 10 11 12 ano 2025 2024 2023
df.replace({'Ignorado': None}, inplace=True)
df.isnull().sum()
data_inversa 0 dia_semana 0 causa_acidente 0 tipo_acidente 0 classificacao_acidente 3 fase_dia 0 sentido_via 0 condicao_metereologica 1834 tipo_pista 0 tracado_via 0 uso_solo 0 feridos 0 veiculos 0 latitude 0 longitude 0 dtype: int64
df.dropna(inplace=True)
df
| data_inversa | dia_semana | causa_acidente | tipo_acidente | classificacao_acidente | fase_dia | sentido_via | condicao_metereologica | tipo_pista | tracado_via | uso_solo | feridos | veiculos | latitude | longitude | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2025-01-01 | quarta-feira | Reação tardia ou ineficiente do condutor | Tombamento | Com VÃtimas Feridas | Pleno dia | Decrescente | Céu Claro | Múltipla | Reta;Declive | Sim | 1 | 2 | -23.485868 | -46.540753 |
| 1 | 2025-01-01 | quarta-feira | Pista esburacada | Colisão frontal | Com VÃtimas Fatais | Pleno dia | Crescente | Céu Claro | Simples | Reta | Não | 1 | 6 | -7.812288 | -39.083333 |
| 2 | 2025-01-01 | quarta-feira | Reação tardia ou ineficiente do condutor | Colisão traseira | Com VÃtimas Feridas | Pleno dia | Crescente | Sol | Dupla | Reta;Aclive | Sim | 3 | 2 | -23.182565 | -50.637228 |
| 3 | 2025-01-01 | quarta-feira | Reação tardia ou ineficiente do condutor | SaÃda de leito carroçável | Com VÃtimas Feridas | Pleno dia | Crescente | Céu Claro | Dupla | Reta | Não | 1 | 2 | -25.365177 | -49.04223 |
| 4 | 2025-01-01 | quarta-feira | Velocidade IncompatÃvel | Colisão frontal | Com VÃtimas Feridas | Pleno dia | Decrescente | Chuva | Simples | Curva;Declive | Não | 2 | 4 | -16.468013 | -43.431213 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 67760 | 2023-09-24 | domingo | Ausência de reação do condutor | Colisão frontal | Com VÃtimas Feridas | Amanhecer | Decrescente | Céu Claro | Simples | Reta | Sim | 3 | 2 | -26,92203838 | -48,95884931 |
| 67761 | 2023-04-19 | quarta-feira | Pedestre andava na pista | Atropelamento de Pedestre | Com VÃtimas Fatais | Plena Noite | Crescente | Céu Claro | Dupla | Reta | Não | 0 | 2 | -25,05467785 | -50,22938892 |
| 67762 | 2023-06-20 | terça-feira | Acessar a via sem observar a presença dos outr... | Colisão transversal | Com VÃtimas Feridas | Plena Noite | Crescente | Céu Claro | Simples | Reta | Sim | 1 | 2 | -3,40552588 | -44,35174989 |
| 67763 | 2023-05-18 | quinta-feira | Conversão proibida | Colisão transversal | Com VÃtimas Feridas | Pleno dia | Crescente | Céu Claro | Simples | Reta | Não | 3 | 2 | -18,69020499 | -39,86154403 |
| 67765 | 2023-08-14 | segunda-feira | Chuva | Queda de ocupante de veÃculo | Com VÃtimas Feridas | Pleno dia | Decrescente | Chuva | Múltipla | Reta | Sim | 1 | 1 | -22,6723488 | -43,28215398 |
144564 rows × 15 columns
df['dia_semana'] = df['dia_semana'].astype('category')
df['causa_acidente'] = df['causa_acidente'].astype('category')
df['tipo_acidente'] = df['tipo_acidente'].astype('category')
df['classificacao_acidente'] = df['classificacao_acidente'].astype('category')
df['fase_dia'] = df['fase_dia'].astype('category')
df['sentido_via'] = df['sentido_via'].astype('category')
df['condicao_metereologica'] = df['condicao_metereologica'].astype('category')
df['tipo_pista'] = df['tipo_pista'].astype('category')
df['tracado_via'] = df['tracado_via'].astype('category')
df['uso_solo'] = df['uso_solo'].astype('category')
df['data_inversa'] = pd.to_datetime(df['data_inversa'])
#Existem datasets com as coordenadas em formato de string
#Para fazer o gráfico de densidade com as localizações no mapa é necessário está em float
def convert_to_float(value):
if isinstance(value, str):
try:
return float(value.replace(',', '.'))
except ValueError:
return value
return value
df['latitude'] = df['latitude'].apply(convert_to_float)
df['longitude'] = df['longitude'].apply(convert_to_float)
df['mes'] = df['data_inversa'].dt.month
df['ano'] = df['data_inversa'].dt.year
df['dia_semana'] = df['data_inversa'].dt.day_name()
traducao_dias = {
'Monday': 'Segunda-feira',
'Tuesday': 'Terça-feira',
'Wednesday': 'Quarta-feira',
'Thursday': 'Quinta-feira',
'Friday': 'Sexta-feira',
'Saturday': 'Sábado',
'Sunday': 'Domingo'
}
df['dia_semana'] = df['dia_semana'].map(traducao_dias)
df
| data_inversa | dia_semana | causa_acidente | tipo_acidente | classificacao_acidente | fase_dia | sentido_via | condicao_metereologica | tipo_pista | tracado_via | uso_solo | feridos | veiculos | latitude | longitude | mes | ano | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2025-01-01 | Quarta-feira | Reação tardia ou ineficiente do condutor | Tombamento | Com VÃtimas Feridas | Pleno dia | Decrescente | Céu Claro | Múltipla | Reta;Declive | Sim | 1 | 2 | -23.485868 | -46.540753 | 1 | 2025 |
| 1 | 2025-01-01 | Quarta-feira | Pista esburacada | Colisão frontal | Com VÃtimas Fatais | Pleno dia | Crescente | Céu Claro | Simples | Reta | Não | 1 | 6 | -7.812288 | -39.083333 | 1 | 2025 |
| 2 | 2025-01-01 | Quarta-feira | Reação tardia ou ineficiente do condutor | Colisão traseira | Com VÃtimas Feridas | Pleno dia | Crescente | Sol | Dupla | Reta;Aclive | Sim | 3 | 2 | -23.182565 | -50.637228 | 1 | 2025 |
| 3 | 2025-01-01 | Quarta-feira | Reação tardia ou ineficiente do condutor | SaÃda de leito carroçável | Com VÃtimas Feridas | Pleno dia | Crescente | Céu Claro | Dupla | Reta | Não | 1 | 2 | -25.365177 | -49.042230 | 1 | 2025 |
| 4 | 2025-01-01 | Quarta-feira | Velocidade IncompatÃvel | Colisão frontal | Com VÃtimas Feridas | Pleno dia | Decrescente | Chuva | Simples | Curva;Declive | Não | 2 | 4 | -16.468013 | -43.431213 | 1 | 2025 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 67760 | 2023-09-24 | Domingo | Ausência de reação do condutor | Colisão frontal | Com VÃtimas Feridas | Amanhecer | Decrescente | Céu Claro | Simples | Reta | Sim | 3 | 2 | -26.922038 | -48.958849 | 9 | 2023 |
| 67761 | 2023-04-19 | Quarta-feira | Pedestre andava na pista | Atropelamento de Pedestre | Com VÃtimas Fatais | Plena Noite | Crescente | Céu Claro | Dupla | Reta | Não | 0 | 2 | -25.054678 | -50.229389 | 4 | 2023 |
| 67762 | 2023-06-20 | Terça-feira | Acessar a via sem observar a presença dos outr... | Colisão transversal | Com VÃtimas Feridas | Plena Noite | Crescente | Céu Claro | Simples | Reta | Sim | 1 | 2 | -3.405526 | -44.351750 | 6 | 2023 |
| 67763 | 2023-05-18 | Quinta-feira | Conversão proibida | Colisão transversal | Com VÃtimas Feridas | Pleno dia | Crescente | Céu Claro | Simples | Reta | Não | 3 | 2 | -18.690205 | -39.861544 | 5 | 2023 |
| 67765 | 2023-08-14 | Segunda-feira | Chuva | Queda de ocupante de veÃculo | Com VÃtimas Feridas | Pleno dia | Decrescente | Chuva | Múltipla | Reta | Sim | 1 | 1 | -22.672349 | -43.282154 | 8 | 2023 |
144564 rows × 17 columns
df.reset_index(inplace=True)
df.drop(columns=['index'], inplace=True)
#Existe um alto número de categorias em causa_acidente e tracado_via, o que aumentou o tempo de treinamento e diminuiu a performace.
limite = 2500
frequencia = df['causa_acidente'].value_counts()
categorias_para_agregar = frequencia[frequencia < limite].index
df['causa_acidente'] = df['causa_acidente'].apply(lambda x: 'Outros' if x in categorias_para_agregar else x)
df['causa_acidente'] = df['causa_acidente'].astype('category')
limite = 2200
frequencia = df['tracado_via'].value_counts()
categorias_para_agregar = frequencia[frequencia < limite].index
df['tracado_via'] = df['tracado_via'].apply(lambda x: 'Outros' if x in categorias_para_agregar else x)
df['tracado_via'] = df['tracado_via'].astype('category')
frequencia = df['tracado_via'].value_counts()
# Identificar categorias que estão abaixo do limite
categorias_para_agregar = frequencia[frequencia > 2200].values
categorias_para_agregar.sum()
117327
frequencia = df['causa_acidente'].value_counts()
categorias_para_agregar = frequencia[frequencia > 2500].values
categorias_para_agregar.sum()
118992
Análise exploratória¶
plt.figure(figsize=(12,6))
agrupado = df.groupby(["mes", "classificacao_acidente"], observed=False).size().reset_index(name="Contagem")
sns.barplot(x = 'mes', y = 'Contagem', hue='classificacao_acidente', data=agrupado)
plt.title(f'Contagem de acidentes de trânsito por Mês e Classificação do acidente')
plt.xlabel('Mês')
plt.ylabel('Contagem')
Text(0, 0.5, 'Contagem')
plt.figure(figsize=(12,6))
agrupado = df.groupby(["dia_semana", "classificacao_acidente"], observed=False).size().reset_index(name="Contagem")
#Para mostrar os dias na ordem correta é preciso fazer a ordernação de forma manual.
ordem_dias = [
'Segunda-feira',
'Terça-feira',
'Quarta-feira',
'Quinta-feira',
'Sexta-feira',
'Sábado',
'Domingo'
]
agrupado['dia_semana'] = pd.Categorical(
agrupado['dia_semana'],
categories=ordem_dias,
ordered=True
)
agrupado = agrupado.sort_values('dia_semana')
sns.barplot(x = 'dia_semana', y = 'Contagem', hue='classificacao_acidente', data=agrupado)
plt.title(f'Contagem de acidentes de trânsito por Dia da semana e Classificação do acidente')
plt.xlabel('Dia da semana')
plt.ylabel('Contagem')
E:\Anaconda1\Lib\site-packages\seaborn\categorical.py:641: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
Text(0, 0.5, 'Contagem')
plt.figure(figsize=(12,6))
agrupado = df.groupby(["ano", "classificacao_acidente"], observed=False).size().reset_index(name="Contagem")
sns.barplot(x = 'ano', y = 'Contagem', hue='classificacao_acidente', data=agrupado)
plt.title(f'Contagem de acidentes de trânsito por Ano e Classificação do acidente')
plt.xlabel('Ano')
plt.ylabel('Contagem')
Text(0, 0.5, 'Contagem')
#Os valores com muitas categorias a contagem aparece embaixo com a ordem correspondente.
colunas = df.select_dtypes(include='category')
for i, col in enumerate(colunas, 1):
if col == 'classificacao_acidente':
continue
agrupado = df.groupby([col, "classificacao_acidente"], observed=False).size().reset_index(name="Contagem")
print(agrupado)
print()
causa_acidente classificacao_acidente \
0 Acessar a via sem observar a presença dos outr... Com VÃtimas Fatais
1 Acessar a via sem observar a presença dos outr... Com VÃtimas Feridas
2 Acessar a via sem observar a presença dos outr... Sem VÃtimas
3 Animais na Pista Com VÃtimas Fatais
4 Animais na Pista Com VÃtimas Feridas
5 Animais na Pista Sem VÃtimas
6 Ausência de reação do condutor Com VÃtimas Fatais
7 Ausência de reação do condutor Com VÃtimas Feridas
8 Ausência de reação do condutor Sem VÃtimas
9 Avarias e/ou desgaste excessivo no pneu Com VÃtimas Fatais
10 Avarias e/ou desgaste excessivo no pneu Com VÃtimas Feridas
11 Avarias e/ou desgaste excessivo no pneu Sem VÃtimas
12 Condutor Dormindo Com VÃtimas Fatais
13 Condutor Dormindo Com VÃtimas Feridas
14 Condutor Dormindo Sem VÃtimas
15 Condutor deixou de manter distância do veÃculo... Com VÃtimas Fatais
16 Condutor deixou de manter distância do veÃculo... Com VÃtimas Feridas
17 Condutor deixou de manter distância do veÃculo... Sem VÃtimas
18 Demais falhas mecânicas ou elétricas Com VÃtimas Fatais
19 Demais falhas mecânicas ou elétricas Com VÃtimas Feridas
20 Demais falhas mecânicas ou elétricas Sem VÃtimas
21 Desrespeitar a preferência no cruzamento Com VÃtimas Fatais
22 Desrespeitar a preferência no cruzamento Com VÃtimas Feridas
23 Desrespeitar a preferência no cruzamento Sem VÃtimas
24 Ingestão de álcool pelo condutor Com VÃtimas Fatais
25 Ingestão de álcool pelo condutor Com VÃtimas Feridas
26 Ingestão de álcool pelo condutor Sem VÃtimas
27 Manobra de mudança de faixa Com VÃtimas Fatais
28 Manobra de mudança de faixa Com VÃtimas Feridas
29 Manobra de mudança de faixa Sem VÃtimas
30 Outros Com VÃtimas Fatais
31 Outros Com VÃtimas Feridas
32 Outros Sem VÃtimas
33 Reação tardia ou ineficiente do condutor Com VÃtimas Fatais
34 Reação tardia ou ineficiente do condutor Com VÃtimas Feridas
35 Reação tardia ou ineficiente do condutor Sem VÃtimas
36 Trafegar com motocicleta (ou similar) entre as... Com VÃtimas Fatais
37 Trafegar com motocicleta (ou similar) entre as... Com VÃtimas Feridas
38 Trafegar com motocicleta (ou similar) entre as... Sem VÃtimas
39 Transitar na contramão Com VÃtimas Fatais
40 Transitar na contramão Com VÃtimas Feridas
41 Transitar na contramão Sem VÃtimas
42 Ultrapassagem Indevida Com VÃtimas Fatais
43 Ultrapassagem Indevida Com VÃtimas Feridas
44 Ultrapassagem Indevida Sem VÃtimas
45 Velocidade IncompatÃvel Com VÃtimas Fatais
46 Velocidade IncompatÃvel Com VÃtimas Feridas
47 Velocidade IncompatÃvel Sem VÃtimas
Contagem
0 739
1 11650
2 1256
3 172
4 2160
5 475
6 1302
7 15950
8 3241
9 63
10 2272
11 259
12 319
13 3360
14 641
15 170
16 7343
17 1479
18 117
19 3064
20 3328
21 63
22 2430
23 254
24 327
25 4130
26 3122
27 414
28 6906
29 1000
30 2611
31 20092
32 2869
33 1091
34 16928
35 3225
36 119
37 2346
38 57
39 1397
40 3064
41 457
42 558
43 2546
44 317
45 777
46 6881
47 1223
tipo_acidente classificacao_acidente Contagem
0 Atropelamento de Animal Com VÃtimas Fatais 165
1 Atropelamento de Animal Com VÃtimas Feridas 1834
2 Atropelamento de Animal Sem VÃtimas 428
3 Atropelamento de Pedestre Com VÃtimas Fatais 1822
4 Atropelamento de Pedestre Com VÃtimas Feridas 4486
5 Atropelamento de Pedestre Sem VÃtimas 69
6 Capotamento Com VÃtimas Fatais 113
7 Capotamento Com VÃtimas Feridas 2428
8 Capotamento Sem VÃtimas 486
9 Colisão com objeto Com VÃtimas Fatais 498
10 Colisão com objeto Com VÃtimas Feridas 7019
11 Colisão com objeto Sem VÃtimas 2772
12 Colisão frontal Com VÃtimas Fatais 2884
13 Colisão frontal Com VÃtimas Feridas 6230
14 Colisão frontal Sem VÃtimas 585
15 Colisão lateral mesmo sentido Com VÃtimas Fatais 383
16 Colisão lateral mesmo sentido Com VÃtimas Feridas 12654
17 Colisão lateral mesmo sentido Sem VÃtimas 2305
18 Colisão lateral sentido oposto Com VÃtimas Fatais 335
19 Colisão lateral sentido oposto Com VÃtimas Feridas 3038
20 Colisão lateral sentido oposto Sem VÃtimas 754
21 Colisão transversal Com VÃtimas Fatais 834
22 Colisão transversal Com VÃtimas Feridas 15930
23 Colisão transversal Sem VÃtimas 1654
24 Colisão traseira Com VÃtimas Fatais 1115
25 Colisão traseira Com VÃtimas Feridas 22104
26 Colisão traseira Sem VÃtimas 4384
27 Derramamento de carga Com VÃtimas Fatais 4
28 Derramamento de carga Com VÃtimas Feridas 80
29 Derramamento de carga Sem VÃtimas 142
30 Engavetamento Com VÃtimas Fatais 68
31 Engavetamento Com VÃtimas Feridas 1920
32 Engavetamento Sem VÃtimas 563
33 Eventos atÃpicos Com VÃtimas Fatais 48
34 Eventos atÃpicos Com VÃtimas Feridas 353
35 Eventos atÃpicos Sem VÃtimas 189
36 Incêndio Com VÃtimas Fatais 4
37 Incêndio Com VÃtimas Feridas 143
38 Incêndio Sem VÃtimas 3079
39 Queda de ocupante de veÃculo Com VÃtimas Fatais 213
40 Queda de ocupante de veÃculo Com VÃtimas Feridas 6253
41 Queda de ocupante de veÃculo Sem VÃtimas 126
42 SaÃda de leito carroçável Com VÃtimas Fatais 1225
43 SaÃda de leito carroçável Com VÃtimas Feridas 15607
44 SaÃda de leito carroçável Sem VÃtimas 4773
45 Sinistro pessoal de trânsito Com VÃtimas Fatais 3
46 Sinistro pessoal de trânsito Com VÃtimas Feridas 7
47 Sinistro pessoal de trânsito Sem VÃtimas 2
48 Tombamento Com VÃtimas Fatais 525
49 Tombamento Com VÃtimas Feridas 11036
50 Tombamento Sem VÃtimas 892
fase_dia classificacao_acidente Contagem
0 Amanhecer Com VÃtimas Fatais 774
1 Amanhecer Com VÃtimas Feridas 4740
2 Amanhecer Sem VÃtimas 1365
3 Anoitecer Com VÃtimas Fatais 533
4 Anoitecer Com VÃtimas Feridas 6235
5 Anoitecer Sem VÃtimas 1088
6 Plena Noite Com VÃtimas Fatais 4927
7 Plena Noite Com VÃtimas Feridas 34865
8 Plena Noite Sem VÃtimas 9393
9 Pleno dia Com VÃtimas Fatais 4005
10 Pleno dia Com VÃtimas Feridas 65282
11 Pleno dia Sem VÃtimas 11357
sentido_via classificacao_acidente Contagem
0 Crescente Com VÃtimas Fatais 5686
1 Crescente Com VÃtimas Feridas 60043
2 Crescente Sem VÃtimas 12194
3 Decrescente Com VÃtimas Fatais 4547
4 Decrescente Com VÃtimas Feridas 50966
5 Decrescente Sem VÃtimas 10779
6 Não Informado Com VÃtimas Fatais 6
7 Não Informado Com VÃtimas Feridas 113
8 Não Informado Sem VÃtimas 230
condicao_metereologica classificacao_acidente Contagem
0 Chuva Com VÃtimas Fatais 914
1 Chuva Com VÃtimas Feridas 11370
2 Chuva Sem VÃtimas 2565
3 Céu Claro Com VÃtimas Fatais 6896
4 Céu Claro Com VÃtimas Feridas 70882
5 Céu Claro Sem VÃtimas 14667
6 Garoa/Chuvisco Com VÃtimas Fatais 280
7 Garoa/Chuvisco Com VÃtimas Feridas 4028
8 Garoa/Chuvisco Sem VÃtimas 1033
9 Granizo Com VÃtimas Fatais 0
10 Granizo Com VÃtimas Feridas 3
11 Granizo Sem VÃtimas 3
12 Neve Com VÃtimas Fatais 0
13 Neve Com VÃtimas Feridas 1
14 Neve Sem VÃtimas 1
15 Nevoeiro/Neblina Com VÃtimas Fatais 155
16 Nevoeiro/Neblina Com VÃtimas Feridas 874
17 Nevoeiro/Neblina Sem VÃtimas 236
18 Nublado Com VÃtimas Fatais 1522
19 Nublado Com VÃtimas Feridas 17142
20 Nublado Sem VÃtimas 3580
21 Sol Com VÃtimas Fatais 456
22 Sol Com VÃtimas Feridas 6654
23 Sol Sem VÃtimas 1074
24 Vento Com VÃtimas Fatais 16
25 Vento Com VÃtimas Feridas 168
26 Vento Sem VÃtimas 44
tipo_pista classificacao_acidente Contagem
0 Dupla Com VÃtimas Fatais 2779
1 Dupla Com VÃtimas Feridas 47394
2 Dupla Sem VÃtimas 10213
3 Múltipla Com VÃtimas Fatais 577
4 Múltipla Com VÃtimas Feridas 11274
5 Múltipla Sem VÃtimas 2035
6 Simples Com VÃtimas Fatais 6883
7 Simples Com VÃtimas Feridas 52454
8 Simples Sem VÃtimas 10955
tracado_via classificacao_acidente Contagem
0 Aclive;Reta Com VÃtimas Fatais 280
1 Aclive;Reta Com VÃtimas Feridas 2141
2 Aclive;Reta Sem VÃtimas 563
3 Curva Com VÃtimas Fatais 1245
4 Curva Com VÃtimas Feridas 13066
5 Curva Sem VÃtimas 2579
6 Curva;Declive Com VÃtimas Fatais 362
7 Curva;Declive Com VÃtimas Feridas 2566
8 Curva;Declive Sem VÃtimas 456
9 Declive;Reta Com VÃtimas Fatais 300
10 Declive;Reta Com VÃtimas Feridas 2039
11 Declive;Reta Sem VÃtimas 410
12 Interseção de Vias Com VÃtimas Fatais 86
13 Interseção de Vias Com VÃtimas Feridas 2996
14 Interseção de Vias Sem VÃtimas 476
15 Outros Com VÃtimas Fatais 1549
16 Outros Com VÃtimas Feridas 21392
17 Outros Sem VÃtimas 4296
18 Reta Com VÃtimas Fatais 5664
19 Reta Com VÃtimas Feridas 61346
20 Reta Sem VÃtimas 13140
21 Reta;Aclive Com VÃtimas Fatais 313
22 Reta;Aclive Com VÃtimas Feridas 2463
23 Reta;Aclive Sem VÃtimas 643
24 Reta;Declive Com VÃtimas Fatais 440
25 Reta;Declive Com VÃtimas Feridas 3113
26 Reta;Declive Sem VÃtimas 640
uso_solo classificacao_acidente Contagem
0 Não Com VÃtimas Fatais 7484
1 Não Com VÃtimas Feridas 61553
2 Não Sem VÃtimas 14032
3 Sim Com VÃtimas Fatais 2755
4 Sim Com VÃtimas Feridas 49569
5 Sim Sem VÃtimas 9171
lats = df['latitude']
lons = df['longitude']
fig = px.density_mapbox(lat=lats, lon=lons, radius=5,
zoom=3, mapbox_style="open-street-map")
fig.update_layout(title="Mapa de Densidade dos acidentes de trânsitos nas rodovias federais")
fig.show()
Treinamento dos modelos¶
df['mes'] = df['mes'].astype("category")
df['ano'] = df['ano'].astype("category")
df['dia_semana'] = df['dia_semana'].astype("category")
df.drop(columns=['data_inversa', 'latitude', 'longitude'], inplace=True)
# Codificação de variáveis categóricas
label_encoders = {}
for col in df.select_dtypes(include=['category']).columns:
le = LabelEncoder()
df[col] = le.fit_transform(df[col])
label_encoders[col] = le
# Definir features e target
y = df['classificacao_acidente']
X = df.drop(columns=['classificacao_acidente', 'veiculos', 'feridos'])
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# Modelos
modelos = {
'Naive Bayes' : GaussianNB(),
'Random Forest': RandomForestClassifier(n_estimators=50, random_state=42),
'SVM': SVC(kernel='rbf', random_state=42),
'RBF Neural Network': MLPClassifier(hidden_layer_sizes=(50,), activation='tanh', solver='adam', max_iter=100, random_state=42)
}
# Treinamento e avaliação
desempenho = {}
shap_values_all_folds = []
X_test_all_folds = []
for nome, modelo in modelos.items():
accs = []
modelo.fit(X_train, y_train)
y_pred = modelo.predict(X_test)
acc = accuracy_score(y_test, y_pred)
print("....")
print()
desempenho[nome] = acc
print(f'\nModelo: {nome}')
print(f'Acurácia: {acc:.4f}')
print(classification_report(y_test, y_pred))
....
Modelo: Naive Bayes
Acurácia: 0.7663
precision recall f1-score support
0 0.29 0.02 0.04 3095
1 0.77 1.00 0.87 33313
2 0.00 0.00 0.00 6962
accuracy 0.77 43370
macro avg 0.35 0.34 0.30 43370
weighted avg 0.61 0.77 0.67 43370
E:\Anaconda1\Lib\site-packages\sklearn\metrics\_classification.py:1471: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior. E:\Anaconda1\Lib\site-packages\sklearn\metrics\_classification.py:1471: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior. E:\Anaconda1\Lib\site-packages\sklearn\metrics\_classification.py:1471: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
....
Modelo: Random Forest
Acurácia: 0.7696
precision recall f1-score support
0 0.34 0.13 0.19 3095
1 0.80 0.94 0.86 33313
2 0.55 0.23 0.32 6962
accuracy 0.77 43370
macro avg 0.56 0.43 0.46 43370
weighted avg 0.73 0.77 0.73 43370
....
Modelo: SVM
Acurácia: 0.7681
precision recall f1-score support
0 0.00 0.00 0.00 3095
1 0.77 1.00 0.87 33313
2 0.00 0.00 0.00 6962
accuracy 0.77 43370
macro avg 0.26 0.33 0.29 43370
weighted avg 0.59 0.77 0.67 43370
E:\Anaconda1\Lib\site-packages\sklearn\metrics\_classification.py:1471: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior. E:\Anaconda1\Lib\site-packages\sklearn\metrics\_classification.py:1471: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior. E:\Anaconda1\Lib\site-packages\sklearn\metrics\_classification.py:1471: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
....
Modelo: RBF Neural Network
Acurácia: 0.7827
precision recall f1-score support
0 0.48 0.05 0.08 3095
1 0.79 0.99 0.87 33313
2 0.74 0.14 0.23 6962
accuracy 0.78 43370
macro avg 0.67 0.39 0.40 43370
weighted avg 0.76 0.78 0.71 43370
E:\Anaconda1\Lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:691: ConvergenceWarning: Stochastic Optimizer: Maximum iterations (100) reached and the optimization hasn't converged yet.
Análise das váriaveis utilizadas no modelo Random Forest¶
#Com vitimas feridas: 1
#Com vitimas fatais: 0
#Sem vitimas: 2
X_sample = X_test.sample(n=5000, random_state=42)
explainer = shap.TreeExplainer(modelos['Random Forest'])
shap_values = explainer.shap_values(X_sample)
shap_values = np.transpose(shap_values, (2, 0 ,1))
#Quanto maior o shap_values, menor a gravidade do acidente
#O feature value indica categoria da váriavel com base no número correspondente ao encoding
for i in range(3):
print(f"\nSummary plot para a classe {i}:")
shap.summary_plot(shap_values[i], X_sample, feature_names=X.columns)
Summary plot para a classe 0:
Summary plot para a classe 1:
Summary plot para a classe 2:
#shap values em números absolutos
shap_values_reshaped = np.concatenate(shap_values, axis=0)
X_sample_repeated = np.repeat(X_sample, repeats=3, axis=0)
shap.summary_plot(
shap_values_reshaped,
X_sample_repeated,
plot_type="bar",
feature_names=X.columns,
)
#Saber quais os códigos de encoding correspondentes as categorias
X_sample_decoded = X_sample.copy()
for col, encoder in label_encoders.items():
if (col == "classificacao_acidente"):
continue
X_sample_decoded[col] = encoder.inverse_transform(X_sample[col])
X_sample_decoded
| dia_semana | causa_acidente | tipo_acidente | fase_dia | sentido_via | condicao_metereologica | tipo_pista | tracado_via | uso_solo | mes | ano | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 74802 | Domingo | Trafegar com motocicleta (ou similar) entre as... | Colisão lateral mesmo sentido | Plena Noite | Crescente | Nublado | Dupla | Reta | Sim | 12 | 2024 |
| 87546 | Quarta-feira | Ausência de reação do condutor | Colisão transversal | Pleno dia | Crescente | Céu Claro | Simples | Curva | Sim | 8 | 2023 |
| 111455 | Domingo | Animais na Pista | Queda de ocupante de veÃculo | Plena Noite | Decrescente | Nublado | Dupla | Reta | Sim | 5 | 2023 |
| 46507 | Sábado | Ausência de reação do condutor | Colisão traseira | Pleno dia | Decrescente | Nublado | Múltipla | Reta | Sim | 5 | 2024 |
| 114726 | Quinta-feira | Ausência de reação do condutor | Tombamento | Plena Noite | Decrescente | Céu Claro | Simples | Outros | Sim | 6 | 2023 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 70816 | Terça-feira | Ausência de reação do condutor | Queda de ocupante de veÃculo | Pleno dia | Crescente | Céu Claro | Simples | Reta | Não | 11 | 2024 |
| 17438 | Quarta-feira | Reação tardia ou ineficiente do condutor | Tombamento | Anoitecer | Crescente | Céu Claro | Dupla | Curva;Declive | Não | 7 | 2024 |
| 38839 | Sexta-feira | Acessar a via sem observar a presença dos outr... | Colisão transversal | Pleno dia | Crescente | Céu Claro | Simples | Reta | Não | 4 | 2024 |
| 24396 | Terça-feira | Trafegar com motocicleta (ou similar) entre as... | Colisão lateral mesmo sentido | Pleno dia | Decrescente | Céu Claro | Dupla | Reta | Não | 1 | 2024 |
| 116422 | Terça-feira | Outros | Colisão com objeto | Pleno dia | Decrescente | Chuva | Dupla | Curva | Não | 6 | 2023 |
5000 rows × 11 columns
X_sample
| dia_semana | causa_acidente | tipo_acidente | fase_dia | sentido_via | condicao_metereologica | tipo_pista | tracado_via | uso_solo | mes | ano | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 74802 | 0 | 12 | 5 | 2 | 0 | 6 | 0 | 6 | 1 | 11 | 1 |
| 87546 | 1 | 2 | 7 | 3 | 0 | 1 | 2 | 1 | 1 | 7 | 0 |
| 111455 | 0 | 1 | 13 | 2 | 1 | 6 | 0 | 6 | 1 | 4 | 0 |
| 46507 | 5 | 2 | 8 | 3 | 1 | 6 | 1 | 6 | 1 | 4 | 1 |
| 114726 | 2 | 2 | 16 | 2 | 1 | 1 | 2 | 5 | 1 | 5 | 0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 70816 | 6 | 2 | 13 | 3 | 0 | 1 | 2 | 6 | 0 | 10 | 1 |
| 17438 | 1 | 11 | 16 | 1 | 0 | 1 | 0 | 2 | 0 | 6 | 1 |
| 38839 | 4 | 0 | 7 | 3 | 0 | 1 | 2 | 6 | 0 | 3 | 1 |
| 24396 | 6 | 12 | 5 | 3 | 1 | 1 | 0 | 6 | 0 | 0 | 1 |
| 116422 | 6 | 10 | 3 | 3 | 1 | 0 | 0 | 1 | 0 | 5 | 0 |
5000 rows × 11 columns
#Relação de multiplo features com os shap_values
#A partir das 4 variaveis mais bem colocadas o proprio shap.dependece_plot encontra as features com maior correlação
top_features = ['tipo_acidente', 'fase_dia', 'dia_semana', 'tipo_pista']
for feature in top_features:
shap.dependence_plot(
ind=feature,
shap_values=shap_values[0],
features=X_sample,
interaction_index="auto",
show=False
)
plt.title(f"Dependency Plot para {feature}")
plt.show()